#ifndef _FILE_WRAPPING_GEOMETRY_H_
#define _FILE_WRAPPING_GEOMETRY_H_

#include <buildspec.h>
#include <Geometry/IFileSerialisable.h>
#include <Geometry/ClientGeometry.h>
#include <Geometry/ClientSimplexProperty.h>
#include <exceptions/GSTRuntimeException.h>
#include <Utils/IPartCountProgress.h>
#include <Client/ClientUtils/Network/NetworkInterfaceStructs.h>
#include <Parsers/GrammarRawStructs.h>

namespace GST{
	//exceptions:
	namespace exceptions 
	{
		class FileOpenProblem
			: public GSTRuntimeException
		{
		public:
			std::string filename;

			FileOpenProblem(const std::string & throwLocation, const std::string& filename)
				: GSTRuntimeException(throwLocation,"")
				, filename(filename)
			{
			}
			virtual ~FileOpenProblem() throw()
			{}
		};
		class NoPersmission
			: public FileOpenProblem
		{
		public:
			NoPersmission(const std::string & throwLocation, const std::string& filename)
				: FileOpenProblem(throwLocation,filename)
			{
				this->_msg = "No permission to open file "+filename+".";
			}
		};

		class FileNotExists
			: public FileOpenProblem
		{
		public:
			FileNotExists(const std::string & throwLocation, const std::string& filename)
				: FileOpenProblem(throwLocation,filename)
			{
				this->_msg = "File "+filename+" does not exists.";
			}
		};
	}
	
	//prototypes:	
namespace ClientUtils {
	struct CrudeFeature;
}

namespace Geometry{

	//prototypes:
	class FileWrappingGeometry;



  /**
	* Due to some format an object file can reside over a set of files (e.g. surpac format: DTM/STR+SSI)
	* This is the base class covering one file.
	*/
struct GST_API_EXPORT FileBundle 
{
	std::string file;

	FileBundle()
	{}
	FileBundle(const std::string & filename)
		: file(filename)
	{
	}

	FileBundle& operator= (const std::string& file)
	{
		this->file = file;
		return *this;
	}
	std::string get() const
	{
		return file;
	}
};

struct GST_API_EXPORT SurpacFileBundle
	: public FileBundle
{
	std::string styleFile;

	SurpacFileBundle()
		: FileBundle()
	{

	}

	void setObjectFile(const std::string & filename)
	{
		this->file = filename;
	}
	void setStyleFile(const std::string & filename)
	{
		this->styleFile = filename;
	}
	std::string getObjectFile() const{ return this->file; }
	std::string getStyleFile() const{ return this->styleFile; }
};

//-----------------------------------------------------------------------------------------------------------

class GST_API_EXPORT TextFileReader
{
public:
	
	TextFileReader();

	ClientGeometryListPtr ReadWrappersFromArchive(const FileBundle & filebundle, const IGeometry::GeometryType& geomtype, Utils::IPartCountProgress * progress );
	ClientGeometryListPtr ReadWrappers(const std::vector<FileBundle> & filenames, const IFileSerialisable::FileType & filetype, const IGeometry::GeometryType& geomtype, Utils::IPartCountProgress * progress );
	ClientGeometryListPtr ReadWrappers(const FileBundle & filebundle, const IFileSerialisable::FileType & filetype, const IGeometry::GeometryType& geomtype, Utils::IPartCountProgress * progress ) ;
	ClientGeometryListPtr getWrappers() const ;
	ClientGeometryListPtr ReleaseWrapper() ;

	static IFileSerialisable::FileType DetermineFileType(const std::string & filename);

private:
	ClientGeometryListPtr container;
};// class TextFileReader

//-------------------------------------------------------------------------------

class GST_API_EXPORT FileWrappingSimplexProperty
	: public ClientSimplexProperty
{
public:
	FileWrappingSimplexProperty( const std::string & propDesc );
	FileWrappingSimplexProperty(const std::string &name,
								PropertyType type,
								int dim,
								PropertyAlignment alignment
								= Geometry::VERTEX_ALIGNED);

	FileWrappingSimplexProperty( const ClientUtils::TableAttributeDesc & p  );
	virtual ~FileWrappingSimplexProperty();
	///@name boost container members
	//@{
	virtual ClientSimplexProperty* clone() const;
	//@}

	///@name GUI and Utils called methods
	//@{
	virtual std::string getName() const;
	virtual void setName(const std::string &name);
	virtual PropertyType getType() const;
	virtual int getDimension() const;
	PropertyAlignment getAlignment() const override;

private:
	std::string name;
	PropertyType type;
	int dim;
	PropertyAlignment alignment;
};

//-------------------------- class of headerfile --------------------------------

class GST_API_EXPORT FileWrappingGeometry
	: public ClientGeometry
{	
	friend class TextFileReader;

protected:
	FileWrappingGeometry();

public:
	///construct empty (File->Request)
	FileWrappingGeometry(IGeometry::GeometryType type, IFileSerialisable::FileType filetype);

	///construct from string (Request->File)
	FileWrappingGeometry(IGeometry::GeometryType type, ClientUtils::CrudeFeature * requestFeature);
	
	virtual ~FileWrappingGeometry();

	///@name ClientGeometry members (lib independent)
	//@{
	unsigned int addSimplexProperty(
		const std::string &name,
		ClientSimplexProperty::PropertyType PropertyType,
		unsigned int dims,
		ClientSimplexProperty::PropertyAlignment alignment
		= Geometry::VERTEX_ALIGNED) override;
	virtual unsigned int addSimplexProperty(const ClientSimplexProperty & p);
	virtual unsigned int addSimplexProperty(const ClientUtils::TableAttributeDesc & p);
	virtual SmplxPropertyListPtr getProperties() const;

	void setPropDesc(const std::string & propertyDesc);
	virtual void setProperties(const SmplxPropertyListPtr & newlist);

	virtual void SaveGeometry(const std::string & filename, const FileType & filetype);
	virtual void SaveProperty(const std::string & filename, const FileType & filetype);

	virtual boost::optional<boost::uint64_t> GetGeometryFileStart() const;
	virtual boost::optional<boost::uint64_t> GetGeometryFileEnd() const;

	//@}

	///@name IFileSerialisable members
	//@{
	virtual void saveToFile(const std::string & filename, const FileType & filetype);
	virtual void saveToFile(const std::string & filestem, const IFileSerialisable::FileType & format, const std::string & geometryStr, const std::string & propDescStr, const std::string & propertyStr);
	virtual void loadFromFile(const std::string & filename, const FileType & filetype);
	virtual void loadPropertyFromFile(const std::string & filename);
	//@}

	//@name StreamposRead
	//@{
	virtual void loadFromStreampos(std::istream & objectStream, const std::streampos & firstPos, const std::streampos & lastPos);
	virtual void loadFromString(const std::string & content);
	//@}

	///@name IGeometry members:
	//@{
	virtual std::string GetName() const;

	virtual bool serializeGeometry(std::ostream & os) const;
	virtual bool serializeSimplexPropertyValues(std::ostream & os) const;
	virtual bool serializeSimplexPropertyDescription(std::ostream & os) const;
	//@}
	
	///@name own interface:
	//@{
		std::string getGeometryString() const;
		void setGeometryString(const std::string& geo);
		void setGridDesc(const Parsers::GridDescription& gd);
		Parsers::GridDescription getGridDesc() const;
	//@}

	std::string geometryString;
	std::string propertyString;
	std::string propertyDesc;
	ClientUtils::SEGYInfoPtr segyInfo;
protected:
	SmplxPropertyListPtr simplexProperties;
	IFileSerialisable::FileType filetype;

	ClientUtils::CrudeFeature * requestFeature;
	boost::optional<boost::uint64_t> geometryFileStart;
	boost::optional<boost::uint64_t> geometryFileEnd;

	Parsers::GridDescription gridDesc;
};

//-----------------------------------------------------------------------------------------------------------

class SurpacWrappingGeometry
	: public FileWrappingGeometry
{
	friend class TextFileReader;

public:
	///construct empty (File->Request)
	SurpacWrappingGeometry(IGeometry::GeometryType type, IFileSerialisable::FileType filetype)
		: FileWrappingGeometry(type, filetype)
	{
	}
	///construct from string (Request->File)
	SurpacWrappingGeometry(IGeometry::GeometryType type, ClientUtils::CrudeFeature * requestFeature)
		: FileWrappingGeometry(type, requestFeature)
	{		   
	}

	//overloads
	virtual bool serializeGeometry(std::ostream & os) const;
	virtual void WriteJsonHeaderPart( std::stringstream & sendingheader, IFileSerialisable::FileType ftype, const int & size ) const;
	virtual void loadFromString(const std::string & content);


	static std::string ExtractStrFile( const std::string &dtmfilename );

protected:
	std::string dtmfile;
};
	
}// namespace Geometry
}// namespace GST


#endif  //_FILE_WRAPPING_GEOMETRY_H_
